﻿#if !defined(linux) && !defined(__linux) && !defined(__linux__)
#error "Support for Linux!"
#endif

#include <stddef.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>

static void alterAttr(struct termios *restrict attribute, int echo)
{
	if (attribute == NULL)
		return;

	attribute->c_lflag &= ~ICANON;	// 取消结束符，匹配立即读取
	if (echo)
		attribute->c_lflag |= ECHO;	// 设置输入回显
	else
		attribute->c_lflag &= ~ECHO;	// 取消输入回显
}

static int get(int echo)
{
	// 获取终端设置
	int fd = STDIN_FILENO;
	struct termios old_attr, new_attr;
	if (tcgetattr(fd, &old_attr) < 0)
	{
		perror("终端设置获取失败");
		return EOF;
	}

	// 保存终端设置
	//cfmakeraw(&new_attr); // 设置原始模式，以字节为单位处理输入数据，处理完毕立即返回
	new_attr = old_attr;

	// 更改终端设置
	alterAttr(&new_attr, echo);
	if (tcsetattr(fd, TCSANOW, &new_attr) < 0)
	{
		perror("终端设置更改失败");
		return EOF;
	}

	// 输入字符
	int key = getchar();

	// 还原终端设置
	if (tcsetattr(fd, TCSANOW, &old_attr) < 0)
		perror("终端设置还原失败");

	return key;
}

int getch(void)
{
	return get(0);
}

int getche(void)
{
	return get(1);
}
